package rollup

import (
	"github.com/consensys/gnark/frontend"
	"github.com/consensys/gnark/std/accumulator/merkle"
	"github.com/consensys/gnark/std/hash/mimc"
)

const (
	nbAccounts = 16 // 16 accounts so we know that the proof length is 5
	depth      = 5  // size fo the inclusion proofs
	batchSize  = 1  // nbTranfers to batch in a proof
)

type Circuit struct {
	// ---------------------------------------------------------------------------------------------
	// SECRET INPUTS

	SenderAccountsBefore [batchSize]AccountConstraints
	SenderAccountsAfter  [batchSize]AccountConstraints

	// list of proofs corresponding to sender account
	MerkleProofsSenderBefore      [batchSize][depth]frontend.Variable
	MerkleProofsSenderAfter       [batchSize][depth]frontend.Variable
	MerkleProofHelperSenderBefore [batchSize][depth - 1]frontend.Variable
	MerkleProofHelperSenderAfter  [batchSize][depth - 1]frontend.Variable

	// ---------------------------------------------------------------------------------------------
	// PUBLIC INPUTS
	// list of root hashes
	RootHashesBefore [batchSize]frontend.Variable `gnark:",public"`
	RootHashesAfter  [batchSize]frontend.Variable `gnark:",public"`
}

// Define declares the circuit's constraints
func (circuit *Circuit) Define(api frontend.API) error {

	// hash function for the merkle proof and the eddsa signature
	hFunc, err := mimc.NewMiMC(api)
	if err != nil {
		return err
	}

	// creation of the circuit
	for i := 0; i < batchSize; i++ {
		api.AssertIsEqual(circuit.SenderAccountsBefore[i].Index, circuit.SenderAccountsAfter[i].Index)
		updatedNonce := api.Add(circuit.SenderAccountsBefore[i].Nonce, 1)
		api.AssertIsEqual(updatedNonce, circuit.SenderAccountsAfter[i].Nonce)
		merkle.VerifyProof(api, hFunc, circuit.RootHashesBefore[i], circuit.MerkleProofsSenderBefore[i][:], circuit.MerkleProofHelperSenderBefore[i][:])
		merkle.VerifyProof(api, hFunc, circuit.RootHashesAfter[i], circuit.MerkleProofsSenderAfter[i][:], circuit.MerkleProofHelperSenderAfter[i][:])
	}

	return nil
}
